//
//  MenuAimationView.m
//  AnimationDemo
//
//  Created by iMuse on 15-7-8.
//  Copyright (c) 2015年 mySelf. All rights reserved.
//

#import "MenuAimationView.h"
#import "MenuItem.h"
#import "ArrowItem.h"

#define  DURATION 0.8f
#define PathDuration 0.5f
#define selectDuration 0.5f
#define backgroundDuration 1.0f
#define KeyAnimation @"KeyAnimation_Menu"
#define GroupAnimation @"GroupAnimation"
#define diameter 60
#define arrowMeter 40
#define topY     2*diameter
#define topX    diameter/2
#define transformScale 1.5
#define SCREEN_WIDTH    [[UIScreen mainScreen]bounds].size.width
#define SCREEN_HEIGHT    [[UIScreen mainScreen]bounds].size.height

@implementation MenuAimationView
{
    UIView * backgroundView;
    
    NSArray * startPointArray;
    NSArray * endPointArray;
    NSMutableArray * arrowEndPointArray;
    NSMutableArray * itemViews;
    NSMutableArray * arrowViews;
    MenuItem  * selectItemView;
    ArrowItem * selectArrowView;
    
    
    NSMutableDictionary * lifeDictionary;
    
    AnimationStatus animationStatus;
}
- (id)initWithFrame:(CGRect)frame andDic:(NSMutableDictionary*) dic
{
    self = [super initWithFrame:frame];
    if (self) {
      
        [self startPointArray];
        [self endPointArray];
        [self arrowPointsArray];
        [self steup];
        lifeDictionary = dic;
        
        [self drawMenu:[dic allKeys]];
    }
    return self;
}
-(void)tapSelfView:(id)sender
{
    if (animationStatus == AnimationBegin)
    {
        [self menuDissForView];
        
    }else if (animationStatus ==AnimationBlowUp)
    {
        [self menuBlowUp];
        
    }else if (animationStatus ==AnimationArrowShow)
    {
        [self arrowHide];
    }
}
-(void) menuDissForView
{
    animationStatus = AnimationEnd;
    for (MenuItem * item in itemViews)
    {
        [self MenuAnimation:item];
    }
    [self animationBackground];
}

-(void)arrowTapClick:(UITapGestureRecognizer*) geuster
{
    ArrowItem * itemView = (ArrowItem*)geuster.view;
    selectArrowView = itemView;
    
    for (ArrowItem * item in arrowViews)
    {
        [self dissArrowView:item];
    }
    [self disArrowCenterView:selectItemView];
    
    if (self.block)
    {
          self.block(selectItemView.label.text,selectArrowView.label.text);
    }
    animationStatus = AnimationEnd;
    
    [self animationBackground];
    
   
}
-(void) arrowHide
{
   
    for (ArrowItem * item in arrowViews)
    {
        [self pathCAKeyframeAnimation:item];
      
    }
    [self menuBlowUp];
    
    

}
-(void) menuBlowUp
{
    animationStatus = AnimationNarrow;
    CGPoint startPoint = CGPointMake(0, 0);
    for (MenuItem * item in itemViews)
    {
        if (item.tag == selectItemView.tag)
        {
            startPoint = self.layer.position;
        }else
        {
            startPoint = [[startPointArray objectAtIndex:item.tag] CGPointValue];
        }
        [self ItemNarrowAnimation:startPoint andEndPoint:[[endPointArray objectAtIndex:item.tag] CGPointValue] andItemView:item];
    }
    animationStatus = AnimationBegin;
}
-(void)tapMenuItemView:(UITapGestureRecognizer*) gesture
{
    MenuItem * currentItemView = (MenuItem*)gesture.view;
    NSInteger  currentTag = currentItemView.tag;
    
    selectItemView = currentItemView;
    
    if (animationStatus ==  AnimationArrowShow)
    {
        return;
    }
    if (animationStatus == AnimationBlowUp)
    {
        [self arrowItemPathAnimation];
        
        return;
    }
    
    animationStatus = AnimationBlowUp;
    
    for (MenuItem * itemView in itemViews)
    {
        if (itemView.tag!=currentTag)
        {
            [self MenuAnimation:itemView];
        }
    }
    
    [self ItmeAnimation:currentItemView];
    
}
-(void)drawMenu:(NSArray*) array
{
    itemViews = [[NSMutableArray alloc] init];
    for (NSInteger index=0; index<array.count; index++)
    {
        UITapGestureRecognizer * tapGuester = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapMenuItemView:)];
        CGPoint point = [[startPointArray objectAtIndex:index] CGPointValue];
        MenuItem * itme = [[MenuItem alloc] initWithFrame:CGRectMake(point.x, point.y, diameter, diameter)];
        [itme setLabelValue:[array objectAtIndex:index]];
   
        itme.tag = index;
    
        itme.layer.bounds = CGRectMake(0, 0, diameter, diameter);
        itme.layer.cornerRadius = diameter/2;
        [itme addGestureRecognizer:tapGuester];
        [self addSubview:itme];
        [itemViews addObject:itme];
        
        [self MenuAnimation:itme];
    }
}

-(void)ItmeAnimation:(MenuItem*) currentItem
{
    CAAnimationGroup * animationGroup = [CAAnimationGroup animation];
    CABasicAnimation * caBasicAnimation = [self itemTranlateAniamtion];
    CAKeyframeAnimation * keyFrameAnimation = [self itemCakframeAnimation:currentItem.layer.position andEndPoint:self.layer.position];
   
    animationGroup.animations = @[caBasicAnimation,keyFrameAnimation];
    animationGroup.duration = DURATION;
    [currentItem.layer addAnimation:animationGroup forKey:GroupAnimation];
    currentItem.layer.position = self.layer.position;
    currentItem.transform = CGAffineTransformMakeScale(transformScale,transformScale);
    
}

-(void)ItemNarrowAnimation:(CGPoint) startPoint andEndPoint:(CGPoint) endPoint andItemView:(MenuItem*) itemView
{
    CAAnimationGroup * animationGroup = [CAAnimationGroup animation];
    CABasicAnimation * caBasicAnimation = [self itemTranlateAniamtion];
    CAKeyframeAnimation * keyFrameAnimation = [self itemCakframeAnimation:startPoint andEndPoint:endPoint];
    
    if (itemView.tag==selectItemView.tag)
    {
         animationGroup.animations = @[caBasicAnimation,keyFrameAnimation];
    }else
    {
         animationGroup.animations = @[keyFrameAnimation];
    }
    animationGroup.duration = DURATION;
    animationGroup.timingFunction = [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseInEaseOut];
    [itemView.layer addAnimation:animationGroup forKey:nil];
    itemView.layer.position = endPoint;
    itemView.transform = CGAffineTransformMakeScale(1,1);
    
}
-(CABasicAnimation*)itemTranlateAniamtion
{
    CABasicAnimation * baseAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    baseAnimation.duration = DURATION;
    
    if (animationStatus==AnimationBlowUp)
    {
        baseAnimation.fromValue = [NSNumber numberWithInt:1];
        baseAnimation.toValue = [NSNumber numberWithFloat:transformScale];
    }else if (animationStatus==AnimationNarrow)
    {
        baseAnimation.fromValue = [NSNumber numberWithFloat:transformScale];
        baseAnimation.toValue = [NSNumber numberWithFloat:1.0];
    }
    return baseAnimation;
}

-(void)dissArrowView:(ArrowItem*)itemArrow
{
    CGFloat fromValue = 0.0;
    CGFloat toValue   =0.0;
    if (itemArrow.arrowTag == selectArrowView.arrowTag)
    {
        fromValue = 1.0;
        toValue  = 2.0;
    }else
    {
        fromValue = 1.0;
        toValue   = 0.0;
    }
    
    CAAnimationGroup* anima = [self animationGroup:fromValue andToVlaue:toValue];
    [itemArrow.layer addAnimation:anima forKey:nil];
 
}
-(void) disArrowCenterView:(MenuItem*) itmeView
{
     CAAnimationGroup* anima = [self animationGroup:2.0 andToVlaue:1.0];
     [itmeView.layer addAnimation:anima forKey:nil];
    
}
-(CAAnimationGroup *) animationGroup:(CGFloat) fromValue andToVlaue:(CGFloat) toValue
{
    CABasicAnimation * base1 = [self arrowItemAnimation:fromValue andToValue:toValue];
    CABasicAnimation * base2 = [self arrowItemOpacityAnimation];
    
    CAAnimationGroup * animationGround = [CAAnimationGroup animation];
    animationGround.delegate = self;
    animationGround.removedOnCompletion = NO;
    animationGround.animations = @[base1,base2];
    animationGround.duration = selectDuration;
    animationGround.fillMode = kCAFillModeForwards;
    return animationGround;
}

-(CABasicAnimation*) arrowItemAnimation:(CGFloat) fromVlue andToValue:(CGFloat)toVlaue
{
    CABasicAnimation * baseAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    baseAnimation.duration = selectDuration;
    baseAnimation.fromValue = [NSNumber numberWithFloat:fromVlue];
    baseAnimation.toValue   = [NSNumber numberWithFloat:toVlaue];
    return baseAnimation;

}

-(CABasicAnimation*) arrowItemOpacityAnimation
{
    CABasicAnimation * baseAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
    baseAnimation.duration = selectDuration;
    
  
    baseAnimation.toValue   = [NSNumber numberWithFloat:0.0];
    return baseAnimation;
}



-(CAKeyframeAnimation*) itemCakframeAnimation:(CGPoint) startPoint andEndPoint:(CGPoint) endPoint
{
    CAKeyframeAnimation * keyFrameAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    NSValue * key1 = [NSValue valueWithCGPoint:startPoint];
    NSValue * key2 = [NSValue valueWithCGPoint:endPoint];
    NSArray * array = @[key1,key2];
    keyFrameAnimation.duration = DURATION;
    keyFrameAnimation.values = array;
    
    return keyFrameAnimation;
}
-(void)MenuAnimation:(MenuItem*) itmeView
{
    CGPoint  startPoint = CGPointMake(0, 0);
    CGPoint  endPoint   = CGPointMake(0, 0);

    CGPoint  point   = CGPointMake(0, 0);
    CGPoint  Point1 = [[startPointArray objectAtIndex:itmeView.tag] CGPointValue] ;
    CGPoint  Point2   = [[endPointArray objectAtIndex:itmeView.tag] CGPointValue] ;
    
    if (animationStatus==AnimationBegin)
    {
        startPoint = Point1;
        endPoint   = Point2;
        point = Point2;
        
    }else if (animationStatus==AnimationEnd || animationStatus==AnimationBlowUp)
    {
        endPoint = Point1;
        startPoint = Point2;
        point = Point1;
    }
    
    CAKeyframeAnimation * keyFrameAnimation = [self itemCakframeAnimation:startPoint andEndPoint:endPoint];
    
    keyFrameAnimation.keyTimes = @[@(0.2),@(0.8)];
    
    keyFrameAnimation.timingFunction = [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseInEaseOut];
    
    [itmeView.layer addAnimation:keyFrameAnimation forKey:KeyAnimation];
    
    itmeView.layer.position = point;
   

}

-(void)arrowPointsArray
{
    NSMutableArray * array = [[NSMutableArray alloc] init];
    CGFloat length = 90.0;
    CGFloat angle = 30;
    
    for (NSInteger index = 0; index<12; index++)
    {
        CGFloat newAngle = angle*(index+1);
        CGFloat endY = length* cos(newAngle/180*M_PI);
        CGFloat endX = length* sin(newAngle/180*M_PI);
        CGPoint point = CGPointMake(self.layer.position.x+endX, self.layer.position.y+endY);
        [array addObject:[NSValue valueWithCGPoint:point]];
        
    }
    arrowEndPointArray = array;
    
}

-(void) pathCAKeyframeAnimation:(ArrowItem*) arrowView
{
    CAAnimationGroup * animationGroup = [CAAnimationGroup animation];
    animationGroup.delegate = self;
    CABasicAnimation * baseAnimation = [self arrowItemOpacityAnimation];
    
    CAKeyframeAnimation * keyAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
   
    CGPoint startPoint = CGPointMake(0,0);
    CGPoint endPoint   = CGPointMake(0, 0);

    
    NSValue * value = [arrowEndPointArray objectAtIndex:arrowView.arrowTag];
    
    CGPoint pointValue = [value CGPointValue];
    
    if (animationStatus == AnimationArrowShow)
    {
        startPoint = pointValue;
        endPoint   = self.layer.position;
        animationGroup.animations = @[baseAnimation,keyAnimation];
       
    }else if (animationStatus == AnimationArrowHide)
    {
        startPoint = self.layer.position;
        endPoint   = pointValue;
        animationGroup.animations = @[keyAnimation];
        
    }
    
   
    CGMutablePathRef thePath = CGPathCreateMutable();
    
    CGPathMoveToPoint(thePath, NULL,startPoint.x,startPoint.y);
    
    CGPathAddQuadCurveToPoint(thePath, NULL, self.layer.position.x ,self.layer.position.y,endPoint.x,endPoint.y);
    keyAnimation.path = thePath;
    keyAnimation.duration = PathDuration;
    
    animationGroup.duration = PathDuration;
    animationGroup.timingFunction = [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseInEaseOut];
    
    animationGroup.removedOnCompletion = NO;
    animationGroup.fillMode = kCAFillModeForwards;
    
    [arrowView.layer addAnimation:animationGroup forKey:nil];
    arrowView.layer.position = endPoint;
   

   
}
-(void)arrowItemPathAnimation
{
    arrowViews = [[NSMutableArray alloc] init];
    NSArray * array = [lifeDictionary valueForKey:selectItemView.label.text];
    
    animationStatus = AnimationArrowHide;
    for (NSInteger index=0; index<array.count; index++)
    {
        UITapGestureRecognizer * tapGuesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(arrowTapClick:)];
        ArrowItem * view = [[ArrowItem alloc] initWithFrame:CGRectMake(0, 0, arrowMeter, arrowMeter)];
        [view addGestureRecognizer:tapGuesture];
        view.layer.borderColor = [UIColor whiteColor].CGColor;
        view.layer.borderWidth = 1;
        view.arrowTag = index;
        view.label.text = [array objectAtIndex:index];
        view.layer.bounds = CGRectMake(0, 0, arrowMeter, arrowMeter);
        view.layer.cornerRadius = arrowMeter/2;
        [self addSubview:view];
        [arrowViews addObject:view];
        [self pathCAKeyframeAnimation:view];
    }
     animationStatus = AnimationArrowShow;
    
}

-(void)steup
{
    UITapGestureRecognizer * tapGuesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapSelfView:)];
    
    [self addGestureRecognizer:tapGuesture];
    backgroundView = [[UIView alloc] init];
    backgroundView.frame = self.bounds;
    backgroundView.backgroundColor = [UIColor blackColor];
    backgroundView.alpha = 0;
    [self addSubview:backgroundView];
    animationStatus = AnimationBegin;
    
}

-(void)animationBackground
{
    if (animationStatus==AnimationBegin)
    {
        [UIView animateWithDuration:backgroundDuration animations:^(){
            backgroundView.alpha = 0.7;
        }];
    }else if (animationStatus==AnimationEnd)
    {
        [UIView animateWithDuration:backgroundDuration animations:^(){
            backgroundView.alpha = 0;
            
        }completion:^(BOOL flinsh){
            [self removeFromSuperview];
            
        }];
    }
}

-(void) startPointArray
{
    CGPoint  point1 = CGPointMake(0-topX, topY);
  
    CGPoint point2      = CGPointMake(SCREEN_WIDTH+topX, topY);
   
    CGPoint point3       = CGPointMake(0-topX, SCREEN_HEIGHT-topY);

    CGPoint point4      = CGPointMake(SCREEN_WIDTH+topX, SCREEN_HEIGHT-topY);
    
    NSArray * array = [NSArray arrayWithObjects:[NSValue valueWithCGPoint:point1],[NSValue valueWithCGPoint:point2],[NSValue valueWithCGPoint:point3],[NSValue valueWithCGPoint:point4], nil];
    
    startPointArray = array;
 
}
-(void)endPointArray
{
    NSInteger X = SCREEN_WIDTH/4;
    NSInteger Y = SCREEN_HEIGHT/4;
 
    CGPoint  point1 = CGPointMake(1.5*X, 1.5*Y);
 
    CGPoint  point2 = CGPointMake(2.5*X, 1.5*Y);

    CGPoint point3 = CGPointMake(1.5*X, 2.5*Y);
    
 
    CGPoint  point4 = CGPointMake(2.5*X, 2.5*Y);
    
    NSArray * array = [NSArray arrayWithObjects:[NSValue valueWithCGPoint:point1],[NSValue valueWithCGPoint:point2],[NSValue valueWithCGPoint:point3],[NSValue valueWithCGPoint:point4],nil];
    endPointArray = array;

}
-(void) animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{

    if ( [anim isKindOfClass:[CAAnimationGroup class]])
    {
    
        if (flag && animationStatus==AnimationBegin)
        {
            for (ArrowItem * itemView in arrowViews)
            {
                if (itemView)
                {
                    [itemView removeFromSuperview];
                }
            }
        }
        
    }
 
    
}
+(UIViewController*) rootViewController
{
    UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
    
    while (topController.presentedViewController) {
        topController = topController.presentedViewController;
    }
    return topController;
}

+(void) AniamtionMenuAction:(NSMutableDictionary*) dic andBlock:(LifeTypeBlock) lifeBlock
{

    UIViewController * rootViewController = [self rootViewController];
    MenuAimationView * menuAniamtion = [[MenuAimationView alloc] initWithFrame:rootViewController.view.bounds  andDic:dic];
    
    [rootViewController.view addSubview:menuAniamtion];
    menuAniamtion.block = lifeBlock;
    [menuAniamtion animationBackground];
    
}

@end
